﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace Xman.Extensions.Core
{
    public static class ObjectExtensions
    {

        /// <summary>
        ///     将对象序列化为JSON字符串，支持存在循环引用的对象
        /// </summary>
        /// <typeparam name="T">动态类型</typeparam>
        /// <param name="value">动态类型对象</param>
        /// <param name="tolower">是否将属性转为首字母小写形式</param>
        /// <returns>JSON字符串</returns>
        public static string ToJson<T>(this T value, bool tolower = false)
        {
            var settings = new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };
            if (!tolower)
            {
                return JsonConvert.SerializeObject(value, settings);
            }
            settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            return JsonConvert.SerializeObject(value, settings);
        }

        /// <summary>
        /// 将对象属性的值转为Collection
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static List<string> ToCollection<T>(this T value) where T:class
        {
            List<string> list = new();
            foreach (var propinfo in value.GetType().GetProperties())
            {
                var propvalue= propinfo.GetValue(value).ToString();
                list.Add(propvalue);
            }
            return list;
        }

        /// <summary>
        /// Obj To T
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T To<T>(this object obj) where T : struct
        {
            try
            {
                if (typeof(T) == typeof(Guid))
                {
                    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(obj.ToString());
                }

                if (typeof(T).IsEnum)
                {
                    if (obj is string)
                        obj = obj.To<int>();

                    if (Enum.IsDefined(typeof(T), obj))
                    {
                        return (T)Enum.Parse(typeof(T), obj.ToString());
                    }
                    else
                    {
                        throw new ArgumentException($"Enum type undefined '{obj}'.");
                    }
                }
                return (T)Convert.ChangeType(obj, typeof(T), CultureInfo.InvariantCulture);
            }
            catch
            {
                return default;
            }
        }

    }
}
